package com.cbg.es.service.impl;

import com.cbg.enums.EsSearchManageExceptionEnum;
import com.cbg.enums.MoveDirectionEnum;
import com.cbg.es.dto.EsColListDTO;
import com.cbg.es.dto.EsTableDTO;
import com.cbg.es.entity.EsCol;
import com.cbg.es.entity.EsTable;
import com.cbg.es.repository.IEsColRepository;
import com.cbg.es.service.IEsColService;
import com.cbg.es.service.IEsTableService;
import com.cbg.es.vo.EsColEditVO;
import com.cbg.es.vo.EsColVO;
import com.cbg.utils.CollectionUtils;
import com.cbg.vo.DirectionsVO;
import com.cbg.vo.StatusVO;
import com.shuyuwl.core.enums.StatusEnum;
import com.shuyuwl.core.exception.SymServiceException;
import com.shuyuwl.core.service.impl.DaoServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 列名备份表 serviceImpl
 *
 * @author wangjuzheng
 * @since 2019-10-16
 */
@Service
@Transactional(rollbackFor = SymServiceException.class)
public class EsColServiceImpl extends DaoServiceImpl<EsCol, Long, IEsColRepository> implements IEsColService {

    @Resource
    private IEsColRepository esColRepository;

    @Resource
    private IEsTableService esTableService;

    @Override
    public List<EsCol> findByTableName(String tableName) {
        return esColRepository.findByTableNameAndStatusOrderBySortAsc(tableName, StatusEnum.OK.getCode());
    }

    @Override
    public List<EsColListDTO> getEsCols(Long tableId) {

        //验证表信息
        EsTable esTable = esTableService.checkEsTable(tableId);
        //根据表名获取没有删除的列信息
        List<EsCol> esCols = esColRepository.findByTableNameAndStatusLessThanOrderBySortAsc(esTable.getTableName(), StatusEnum.DELETE.getCode());
        List<EsColListDTO> list = new ArrayList<>();
        //当存在列信息时
        if (CollectionUtils.isNotEmpty(esCols)) {
            for (EsCol esCol : esCols) {
                EsColListDTO esColListDTO = getEsColListDTO(esCol);
                list.add(esColListDTO);
            }
        }
        return list;
    }

    @Override
    public void addEsCOl(EsColVO esColVO) {

        //验证表是否处于-启用状态
        EsTable esTable = esTableService.checkEsTable(esColVO.getTableId());
        List<EsCol> list = esColRepository.findByTableNameAndColNameAliasAndStatusLessThan(esTable.getTableName(), esColVO.getColNameAlias().trim(), StatusEnum.DELETE.getCode());
        //列名已经存在
        if (CollectionUtils.isNotEmpty(list)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_NAME_NOT_NULL.getMsg());
        }
        esColRepository.getMaxSOrt(esTable.getTableName(), StatusEnum.DELETE.getCode());
        EsCol esCoCol = new EsCol();
        BeanUtils.copyProperties(esColVO, esCoCol);
        //排序
        Integer sort = esColRepository.getMaxSOrt(esTable.getTableName(), StatusEnum.DELETE.getCode());
        esCoCol.setSort(sort == null ? 1 : sort + 1);
        //表名称
        esCoCol.setTableName(esTable.getTableName());
        esColRepository.save(esCoCol);
    }

    @Override
    public void updateEsCol(EsColEditVO esColEditVO) {

        EsCol esCol = esColRepository.findByIdAndStatusLessThan(esColEditVO.getColId(), StatusEnum.DELETE.getCode());
        //列信息不存在
        if (esCol == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_NULL.getMsg());
        }
        List<EsCol> list = esColRepository.findByTableNameAndColNameAliasAndStatusLessThan(esCol.getTableName(), esColEditVO.getColNameAlias().trim(), StatusEnum.DELETE.getCode());
        //列名已经存在
        if (CollectionUtils.isNotEmpty(list)) {
            if (list.size() > 1 || !list.get(0).getId().equals(esCol.getId())) {
                throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_NAME_NOT_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_NAME_NOT_NULL.getMsg());
            }
        }

        //列的修改
        //列显示名
        esCol.setColNameAlias(esColEditVO.getColNameAlias());
        //排序
        esCol.setStatus(esColEditVO.getStatus());
        esColRepository.save(esCol);
    }

    @Override
    public void deleteEsCol(List<Long> ids) {

        //请选择需要删除的列
        if (CollectionUtils.isEmpty(ids)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_DELETE_IDS_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_DELETE_IDS_NULL.getMsg());
        }
        esColRepository.updateEsCol(ids, StatusEnum.DELETE.getCode());
    }

    @Override
    public void deleteByTableName(String tableName) {
        esColRepository.deleteByTableName(tableName, StatusEnum.DELETE.getCode());
    }

    @Override
    public EsColListDTO getDetails(Long id) {

        //列id不存在
        if (id == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_ID_NULL.getMsg());
        }
        EsCol esCol = esColRepository.findByIdAndStatusLessThan(id, StatusEnum.DELETE.getCode());

        //列信息不存在
        if (esCol == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_NULL.getMsg());
        }
        return getEsColListDTO(esCol);
    }

    /**
     * 格式化数据
     *
     * @param esCol 列信息
     * @return 列的列表信息
     */
    private EsColListDTO getEsColListDTO(EsCol esCol) {

        EsColListDTO esColListDTO = new EsColListDTO();
        //列id
        esColListDTO.setColId(esCol.getId());
        //表名称
        esColListDTO.setTableName(esCol.getTableName());
        //列名
        esColListDTO.setName(esCol.getName());
        //列注释
        esColListDTO.setNameCn(esCol.getNameCn());
        //列显示名
        esColListDTO.setColNameAlias(esCol.getColNameAlias());
        //状态
        esColListDTO.setStatus(esCol.getStatus());
        return esColListDTO;
    }

    @Override
    public void updateEsColStatus(StatusVO statusVO) {

        //列id不存在
        if (CollectionUtils.isEmpty(statusVO.getIds())) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_ID_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_ID_NULL.getMsg());
        }
        esColRepository.updateEsCol(statusVO.getIds(), statusVO.getStatus());
    }

    @Override
    public void updateDirections(DirectionsVO directionsVO) {

        EsCol esCol = esColRepository.findByIdAndStatusLessThan(directionsVO.getId(), StatusEnum.DELETE.getCode());
        //参数验证
        EsTableDTO esTableDTO = esTableService.getDetails(directionsVO.getPid());

        List<EsCol> list = esColRepository.findByTableNameAndStatusLessThanOrderBySortAsc(esTableDTO.getTableName(), StatusEnum.DELETE.getCode());
        //列信息不存在
        if (CollectionUtils.isEmpty(list)) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_NULL.getMsg());
        }

        //获取需要移动类的下标
        int currentIndex = list.indexOf(esCol);
        //当前列不在这张表下
        if (currentIndex == -1) {
            throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_COL_TABLE_EQUALS_NULL.getCode(), EsSearchManageExceptionEnum.ERROR_COL_TABLE_EQUALS_NULL.getMsg());
        }
        MoveDirectionEnum directionEnum = MoveDirectionEnum.getDirectionByCode(directionsVO.getDirectionType());
        //请选择正确的移动方向
        if (directionEnum == null) {
            throw new SymServiceException(EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getCode(), EsSearchManageExceptionEnum.MOVE_DIRECTION_NULL.getMsg());
        }

        //列的移动
        moveCategoryDirections(currentIndex, esCol, directionEnum, list);
    }

    /**
     * 分类的位移
     *
     * @param currentIndex  移动类在所属分类下的下标
     * @param esCol         需要移动类信息
     * @param directionEnum 移动位置枚举
     * @param list          分类列表信息
     */
    private void moveCategoryDirections(int currentIndex, EsCol esCol, MoveDirectionEnum directionEnum, List<EsCol> list) {

        switch (directionEnum) {
            case UP:
                //上移，需要和前一个商品交换下标
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                EsCol previous = list.get(currentIndex - 1);
                previous.setSort(previous.getSort() + 1);
                esCol.setSort(esCol.getSort() - 1);
                esColRepository.save(previous);
                esColRepository.save(esCol);
                break;
            case DOWN:
                //下移
                if (currentIndex == list.size() - 1) {
                    //已经是最后一个，无法下移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                EsCol next = list.get(currentIndex + 1);
                next.setSort(next.getSort() - 1);
                esCol.setSort(esCol.getSort() + 1);
                esColRepository.save(next);
                esColRepository.save(esCol);

                break;
            case TOP:
                //置顶
                if (currentIndex == 0) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_TOP.getMsg());
                }
                esCol.setSort(list.get(0).getSort());
                esColRepository.save(esCol);

                for (int i = 0; i < currentIndex; i++) {
                    EsCol newEsCategory = list.get(i);
                    newEsCategory.setSort(newEsCategory.getSort() + 1);
                    esColRepository.save(newEsCategory);
                }
                break;
            case LAST:
                //置底
                if (currentIndex == list.size() - 1) {
                    //已经是第一个，无法上移
                    throw new SymServiceException(EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getCode(), EsSearchManageExceptionEnum.ERROR_MOVE_DIRECTION_DOWN.getMsg());
                }
                esCol.setSort(list.get(list.size() - 1).getSort());
                esColRepository.save(esCol);

                for (int i = currentIndex + 1; i < list.size(); i++) {
                    EsCol newEsCategory = list.get(i);
                    newEsCategory.setSort(newEsCategory.getSort() - 1);
                    esColRepository.save(newEsCategory);
                }
                break;
            default:
                break;
        }
    }
}
